package xyz.myachin.saveto.logic.intent

import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Parcelable
import android.provider.DocumentsContract
import xyz.myachin.saveto.settings.Settings
import java.io.File

class IntentProcessor(private val mIntent: Intent) {
    var mRemoveIntent: Intent? = null
        private set

    lateinit var mContentType: ContentType
        private set

    var extraText: String = ""
        private set

    fun getContentTypeForIntent(): ContentType {
        if (mIntent.action == ACTION_DOWNLOADED && !mIntent.hasExtra(ORIGINAL_URI)) return ContentType.DAMAGED
        if (mIntent.action == ACTION_DOWNLOADED_DIRECT_CHOOSER && !mIntent.hasExtra(ORIGINAL_URI)) return ContentType.DAMAGED
        if (mIntent.action == ACTION_DOWNLOADED_MANUAL_CHOOSER && !mIntent.hasExtra(ORIGINAL_URI)) return ContentType.DAMAGED

        if (mIntent.action == Intent.ACTION_SEND ||
            mIntent.action == ACTION_DOWNLOADED ||
            mIntent.action == ACTION_DOWNLOADED_DIRECT_CHOOSER ||
            mIntent.action == ACTION_DOWNLOADED_MANUAL_CHOOSER
        ) {
            val result = when {
                mIntent.hasExtra(Intent.EXTRA_STREAM) -> ContentType.FILE

                mIntent.hasExtra(Intent.EXTRA_TEXT) -> {
                    extraText = mIntent.getStringExtra(Intent.EXTRA_TEXT)!!
                    if (!Settings.useDownloader) {
                        ContentType.TEXT
                    } else {
                        if (mIntent.getStringExtra(Intent.EXTRA_TEXT)!!
                                .contains(Regex("^[\\w]+://.*$"))
                        ) {
                            if (mIntent.getStringExtra(Intent.EXTRA_TEXT)!!
                                    .startsWith("http", true)
                            ) {
                                ContentType.GOOD_URL
                            } else {
                                ContentType.BAD_URL
                            }
                        } else {
                            ContentType.TEXT
                        }
                    }
                }
                else -> ContentType.UNKNOWN
            }
            mContentType = result
            return result
        }
        return ContentType.UNKNOWN
    }

    fun getCreateFileIntent(): Intent {
        return Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
            type = mIntent.type
            addCategory(Intent.CATEGORY_OPENABLE)
            putExtra(Intent.EXTRA_TITLE, getFileName())
            if (Build.VERSION.SDK_INT >= 26) {
                val uri = when (mContentType) {
                    ContentType.FILE -> streamDataUri
                    ContentType.TEXT -> mIntent.data
                    else -> null
                }
                putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri)
            }
        }
    }

    val streamDataUri = (mIntent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)

    private fun createRemoveFileIntent(id: Long) {
        Intent(ACTION_NEED_REMOVE).run {
            putExtra(FILE_ID, id)
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            mRemoveIntent = this
        }
    }

    private fun getOfferedUri(): Uri? {
        if (mIntent.hasExtra(ORIGINAL_URI)) {
            createRemoveFileIntent(mIntent.getLongExtra(FILE_ID, -1))
            return Uri.parse(mIntent.getStringExtra(ORIGINAL_URI))
        }
        return streamDataUri
    }

    fun getFileName(): String {
        if (extraText.isNotEmpty()) {
            if (Settings.textLength > -1) {
                return extraText.take(Settings.textLength).trim().plus(".txt")
            }
            return "TextFile.txt"
        }

        val fn = "filename"
        val typeMod = mIntent.type!!.substringAfter("/")

        val stub = "$fn.$typeMod"
        val filename = "?$fn="
        var result = when {
            getOfferedUri()?.path == null -> stub
            getOfferedUri()?.path!!.contains(filename) -> getOfferedUri()?.path!!.substringAfter(
                filename
            )
                .substringBefore("/")
            !getOfferedUri()?.lastPathSegment.isNullOrEmpty() -> "${getOfferedUri()?.lastPathSegment}"
            else -> stub
        }
        File(result).extension.also {
            if (it.isEmpty() || it.isBlank() || it.length > 5) {
                result = result.plus(".$typeMod")
            }
        }
        return result.replace(":", "_")
    }
}